<?php

namespace addons\cloud_market\controller;

use addons\cloud_market\model\CloudMarketUser;
use app\common\model\user\User;
use hiduoke\controller\AddonsController;
use think\facade\Db;
use think\Exception;

class Migrate extends AddonsController
{
    protected $notLogin = ['*'];
    protected $notCheck = ['*'];

    protected $tables = array(
        // 应用
        ['fa_dk_addon', 'dk_cloud_market_addon'],
        ['fa_dk_label', 'dk_cloud_market_label'],
        ['fa_dk_addon_versions', 'dk_cloud_market_addon_versions'],
        ['fa_dk_addon_minapp', 'dk_cloud_market_addon_minapp'],
        ['fa_dk_addon_sku', 'dk_cloud_market_addon_sku'],
        //        // 程序
        ['fa_dk_program', 'dk_cloud_market_program'],
        //        // 站点
        ['fa_dk_site', 'dk_cloud_market_site'],
        ['fa_dk_site_addon', 'dk_cloud_market_site_addon'],
        ['fa_dk_site_addon_token', 'dk_cloud_market_site_addon_token'],
        // 用户
        ['fa_user', 'dk_cloud_market_user'],
        ['fa_dk_user_developer', 'dk_cloud_market_developer'],
        ['fa_dk_order', 'dk_cloud_market_order'],
        //        // 产品列表
        ['fa_product', 'dk_cloud_market_product'],
        ['fa_product_agent', 'dk_cloud_market_product_agent'],
        ['fa_product_token', 'dk_cloud_market_product_token'],
        ['fa_product_user', 'dk_cloud_market_product_user'],
        //        // 文档
        ['fa_docs', 'dk_cloud_market_docs'],
        ['fa_docs_content', 'dk_cloud_market_docs_content'],
        //        // 问答
        ['fa_question', 'dk_cloud_market_question'],
        ['fa_question_answer', 'dk_cloud_market_question_answer'],
        //        // 临时废除
        ////        ['fa_question_favorite', 'dk_cloud_market_question_favorite'],
        ////        ['fa_question_like', 'dk_cloud_market_question_like'],
        ////        ['fa_question_tag', 'dk_cloud_market_question_tag']
        //        // DIY
        ['fa_diy', 'dk_cloud_market_diy'],
        ['fa_dk_ad', 'dk_cloud_market_ad'],


    );

    protected function initialize()
    {
        parent::initialize();
    }

    public function index()
    {
        $results = [];
        foreach ($this->tables as $table) {
            $oldTable = $table[0];
            $newTable = $table[1];

            echo "<h3>正在迁移: {$oldTable} -> {$newTable}</h3>";

            try {
                $result = $this->migrate($oldTable, $newTable);
                $results[] = [
                    'old_table' => $oldTable,
                    'new_table' => $newTable,
                    'status'    => 'success',
                    'message'   => $result['message'],
                    'count'     => $result['count']
                ];
                echo "<p style='color: green;'>✓ 成功: {$result['message']}</p>";
            } catch (Exception $e) {
                $results[] = [
                    'old_table' => $oldTable,
                    'new_table' => $newTable,
                    'status'    => 'error',
                    'message'   => $e->getMessage(),
                    'count'     => 0
                ];
                echo "<p style='color: red;'>✗ 失败: {$e->getMessage()}</p>";
            }

            echo "<hr>";
        }

        // 输出总结
        echo "<h2>迁移总结</h2>";
        $successCount = 0;
        $errorCount = 0;
        foreach ($results as $result) {
            if ($result['status'] === 'success') {
                $successCount++;
                echo "<p>✓ {$result['old_table']} -> {$result['new_table']}: {$result['count']} 条记录</p>";
            } else {
                $errorCount++;
                echo "<p>✗ {$result['old_table']} -> {$result['new_table']}: {$result['message']}</p>";
            }
        }

        echo "<p><strong>成功: {$successCount} 个表, 失败: {$errorCount} 个表</strong></p>";
    }


    /**
     * 清空所有新表的数据
     */
    public function truncateAll()
    {
        $results = [];
        $successCount = 0;
        $errorCount = 0;

        echo "<h2>清空所有新表数据</h2>";
        echo "<p style='color: red;'><strong>警告：此操作将清空所有目标表的数据，请确认操作！</strong></p>";

        // 获取确认参数
        $confirm = $this->request->param('confirm', '');
        if ($confirm !== 'yes') {
            echo "<p>如需执行清空操作，请在URL后添加参数: &confirm=yes</p>";
            echo "<p>例如: /migrate/truncateAll?confirm=yes</p>";
//            return json(['code' => 0, 'msg' => '需要确认参数']);
            return "";
        }

        foreach ($this->tables as $table) {
            $newTable = $table[1]; // 获取新表名

            echo "<h4>正在清空表: {$newTable}</h4>";

            try {
                if ($this->tableExists($newTable)) {
                    // 获取清空前的记录数
                    $beforeCount = Db::table($newTable)->count();

                    // 清空表数据
                    Db::execute("TRUNCATE TABLE {$newTable}");

                    $results[] = [
                        'table'   => $newTable,
                        'status'  => 'success',
                        'message' => "成功清空 {$beforeCount} 条记录"
                    ];

                    $successCount++;
                    echo "<p style='color: green;'>✓ 成功清空 {$beforeCount} 条记录</p>";
                } else {
                    $results[] = [
                        'table'   => $newTable,
                        'status'  => 'skip',
                        'message' => '表不存在，跳过'
                    ];
                    echo "<p style='color: orange;'>⚠ 表不存在，跳过</p>";
                }
            } catch (Exception $e) {
                $results[] = [
                    'table'   => $newTable,
                    'status'  => 'error',
                    'message' => $e->getMessage()
                ];
                $errorCount++;
                echo "<p style='color: red;'>✗ 失败: {$e->getMessage()}</p>";
            }

            echo "<hr>";
        }

        // 输出总结
        echo "<h3>清空操作总结</h3>";
        echo "<p><strong>成功清空: {$successCount} 个表</strong></p>";
        if ($errorCount > 0) {
            echo "<p><strong style='color: red;'>失败: {$errorCount} 个表</strong></p>";
        }
//
//        return json([
//            'code' => 1,
//            'msg' => "清空操作完成，成功: {$successCount} 个表，失败: {$errorCount} 个表",
//            'data' => $results
//        ]);
    }


    public function userInstall()
    {
        $market_users = (new CloudMarketUser())->select();
        foreach ($market_users as $key => $market_user) {
            $userModel = (new User())->where(['username' => $market_user['username']])->findOrEmpty();
            if (!$userModel->isEmpty()) {
                continue;
            }
            $data = array(
                'avatar'   => $market_user['avatar'],
                'username' => $market_user['username'],
                'password' => $market_user['password'],
                'salt'     => $market_user['salt'],
                'phone'    => $market_user['mobile'],
                'email'    => $market_user['email'],
                'login_ip' => $market_user['loginip'],
                'join_ip'  => $market_user['joinip'],
            );
            $userModel->save($data);
            $market_user->uid = $userModel->uid;
            $market_user->save();
        }
    }


    /**
     * 转换时间字段名称
     * @param array $data
     * @return array
     */
    private function convertTimeFields($data)
    {
        $timeFieldMap = [
            'createtime' => 'create_time',
            'updatetime' => 'update_time',
            'deletetime' => 'delete_time'
        ];

        $convertedData = [];
        foreach ($data as $key => $value) {
            if (isset($timeFieldMap[$key])) {
                $convertedData[$timeFieldMap[$key]] = $value;
            } else {
                $convertedData[$key] = $value;
            }
        }

        return $convertedData;
    }

    /**
     * 数据迁移方法
     * @param string $oldTable 源表名
     * @param string $newTable 目标表名
     * @return array
     * @throws Exception
     */
    public function migrate($oldTable, $newTable)
    {
        try {
            // 开启事务
            Db::startTrans();

            // 检查源表是否存在
            if (!$this->tableExists($oldTable)) {
                throw new Exception("源表 {$oldTable} 不存在");
            }

            // 检查目标表是否存在
            if (!$this->tableExists($newTable)) {
                throw new Exception("目标表 {$newTable} 不存在");
            }

            // 获取源表数据
            $sourceData = Db::table($oldTable)->select();

            if (empty($sourceData)) {
                Db::commit();
                return [
                    'message' => "源表 {$oldTable} 没有数据需要迁移",
                    'count'   => 0
                ];
            }

            // 获取目标表字段结构
            $targetFields = $this->getTableFields($newTable);

            // 处理数据迁移
            $successCount = 0;
            $errorCount = 0;

            foreach ($sourceData as $row) {
                try {
                    // 转换时间字段名称
                    $row = $this->convertTimeFields($row);
                    // 过滤数据，只保留目标表存在的字段
                    $filteredData = $this->filterDataByFields($row, $targetFields);

                    if (!empty($filteredData)) {
                        // 检查是否已存在相同记录（基于主键或唯一键）
                        if (!$this->recordExists($newTable, $filteredData)) {
                            Db::table($newTable)->insert($filteredData);
                            $successCount++;
                        } else {
                            // 可选择更新现有记录
//                             Db::table($newTable)->where('id', $filteredData['id'])->update($filteredData);
                        }
                    }
                } catch (Exception $e) {
                    $errorCount++;
                    // 记录错误但继续处理其他记录
                    echo "<p style='color: orange;'>警告: 记录迁移失败 - {$e->getMessage()}</p>";
                }
            }

            Db::commit();

            $message = "成功迁移 {$successCount} 条记录";
            if ($errorCount > 0) {
                $message .= "，{$errorCount} 条记录失败";
            }

            return [
                'message' => $message,
                'count'   => $successCount
            ];

        } catch (Exception $e) {
            Db::rollback();
            throw new Exception("迁移失败: " . $e->getMessage());
        }
    }

    /**
     * 检查表是否存在
     * @param string $tableName
     * @return bool
     */
    private function tableExists($tableName)
    {
        try {
            $tables = Db::query("SHOW TABLES LIKE '{$tableName}'");
            return !empty($tables);
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * 获取表字段信息
     * @param string $tableName
     * @return array
     */
    private function getTableFields($tableName)
    {
        try {
            $fields = Db::query("SHOW COLUMNS FROM {$tableName}");
            return array_column($fields, 'Field');
        } catch (Exception $e) {
            return [];
        }
    }

    /**
     * 根据目标表字段过滤数据
     * @param array $data
     * @param array $targetFields
     * @return array
     */
    private function filterDataByFields($data, $targetFields)
    {
        $filteredData = [];
        foreach ($data as $key => $value) {
            if (in_array($key, $targetFields)) {
                $filteredData[$key] = $value;
            }
        }
        return $filteredData;
    }

    /**
     * 检查记录是否已存在
     * @param string $tableName
     * @param array $data
     * @return bool
     */
    private function recordExists($tableName, $data)
    {
        // 如果有id字段，使用id检查
        if (isset($data['id'])) {
            $exists = Db::table($tableName)->where('id', $data['id'])->find();
            return !empty($exists);
        }

        // 如果没有id字段，可以根据其他唯一字段检查
        // 这里可以根据具体业务需求调整
        return false;
    }

    /**
     * 单表迁移接口（可通过URL参数调用）
     */
    public function single()
    {
        $oldTable = $this->request->param('old_table');
        $newTable = $this->request->param('new_table');

        if (!$oldTable || !$newTable) {
            return json(['code' => 0, 'msg' => '请提供源表名和目标表名']);
        }

        try {
            $result = $this->migrate($oldTable, $newTable);
            return json(['code' => 1, 'msg' => $result['message'], 'data' => $result]);
        } catch (Exception $e) {
            return json(['code' => 0, 'msg' => $e->getMessage()]);
        }
    }

    /**
     * 清空目标表数据（谨慎使用）
     */
    public function truncate()
    {
        $tableName = $this->request->param('table');

        if (!$tableName) {
            return json(['code' => 0, 'msg' => '请提供表名']);
        }

        try {
            if ($this->tableExists($tableName)) {
                Db::execute("TRUNCATE TABLE {$tableName}");
                return json(['code' => 1, 'msg' => "表 {$tableName} 已清空"]);
            } else {
                return json(['code' => 0, 'msg' => "表 {$tableName} 不存在"]);
            }
        } catch (Exception $e) {
            return json(['code' => 0, 'msg' => $e->getMessage()]);
        }
    }
}
